package com.yq.interview.study.thread;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @ClassName CASDemo
 * @Description CAS:比较并交换
 * @Author yaoqiang
 * @Date 2020/11/16 11:08
 * @Version 1.0
 *
 * unsafe是用native修饰的，
 * 是CPU的并发原语
 * 功能：判断某个位置值是否为预期值，如果是，更新，否则，返回false，过程是原子的。
 */
public class CASDemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger = new AtomicInteger(5);
        System.out.println(atomicInteger.compareAndSet(5, 2020));//true
        System.out.println(atomicInteger.getAndIncrement());//2020  unsafe.getAndAddInt(this, valueOffset, 1); 当前对象，内存偏移量,可以向内存一样操作这个包
        System.out.println(atomicInteger.get());//2021
        System.out.println(atomicInteger.incrementAndGet());//2022

        ///ABA产生方式
        new Thread(()->{
            atomicReference.compareAndSet(100,101);
            atomicReference.compareAndSet(101,100);
        },"t1").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(atomicReference.compareAndSet(100,2019)+"\t"+atomicReference.get());
        },"t2").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ///ABA解决方式 AtomicStampedReference

        new Thread(()->{
            int stamp=atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第一次版本号"+stamp);
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            atomicStampedReference.compareAndSet(100,101,atomicStampedReference.getStamp(),2);
            System.out.println(Thread.currentThread().getName()+"第2次版本号"+atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),3);
            System.out.println(Thread.currentThread().getName()+"第3次版本号"+atomicStampedReference.getStamp());
        },"t3").start();

        new Thread(()->{
            int stamp=atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第一次版本号"+stamp);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           boolean b=  atomicStampedReference.compareAndSet(100,2020,stamp,stamp+1);

            System.out.println(Thread.currentThread().getName()+"第二次是否修改成功" +b+"当前最新实际版本号"+atomicStampedReference.getStamp());
            System.out.println("当前实际最新值"+atomicStampedReference.getReference());
        },"t4").start();
    }
    static AtomicReference<Integer> atomicReference=new AtomicReference<>(100);
    static AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference<>(100,1);
}
